package com.fx.device.service.activit.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fx.device.common.util.ErrorEnum;
import com.fx.device.common.util.ReturnMessage;
import com.fx.device.common.util.ReturnMessageUtils;
import com.fx.device.common.util.SecurityUtil;
import com.fx.device.repository.ActivitFormdataRepository;
import com.fx.device.repository.ProUserRepository;
import com.fx.device.service.activit.ProcessDefinitionService;
import com.fx.device.vo.activit.Formdata;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipInputStream;


@Service
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {

    final private RepositoryService repositoryService;
    final private ProcessRuntime processRuntime;
    final private SecurityUtil securityUtil;
    final private ProUserRepository proUserRepository;
    final private ActivitFormdataRepository activitFormdataRepository;


    @Override
    public ReturnMessage<Object> uploadStreamAndDeployment(MultipartFile multipartFile, String deploymentName) {
        String fileName = multipartFile.getOriginalFilename();

        try {
            // 得到输入流（字节流）对象
            InputStream fileInputStream = multipartFile.getInputStream();

            // 文件的扩展名
            String extension = FilenameUtils.getExtension(fileName);

            // ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//创建处理引擎实例
            // repositoryService = processEngine.getRepositoryService();//创建仓库服务实例

            Deployment deployment = null;
            if (extension.equals("zip")) {
                ZipInputStream zip = new ZipInputStream(fileInputStream);
                deployment = repositoryService.createDeployment()//初始化流程
                        .addZipInputStream(zip)
                        .name(deploymentName)
                        .deploy();
            } else {
                deployment = repositoryService.createDeployment()//初始化流程
                        .addInputStream(fileName, fileInputStream)
                        .name(deploymentName)
                        .deploy();
            }

            return ReturnMessageUtils.success(
                    deployment.getId() + ";" + fileName + ";"
                            + deployment.getName());

        } catch (Exception e) {
            return ReturnMessageUtils.error(ErrorEnum.E_ACTIVIT_DEFINITION.getErrorCode(),
                    ErrorEnum.E_ACTIVIT_DEFINITION.getErrorMsg(), e.toString());
        }
    }

    @Override
    public ReturnMessage<Object> upload(MultipartFile multipartFile) {
        if (multipartFile.isEmpty()) {
            System.out.println("文件为空");
        }
        String fileName = multipartFile.getOriginalFilename();  // 文件名
        String suffixName = fileName.substring(fileName.lastIndexOf("."));  // 后缀名
        String filePath = ReturnMessageUtils.BPMN_PathMapping; // 上传后的路径

        //本地路径格式转上传路径格式
        filePath = filePath.replace("\\", "/");
        filePath = filePath.replace("file:", "");

        // String filePath = request.getSession().getServletContext().getRealPath("/") + "bpmn/";
        fileName = UUID.randomUUID() + suffixName; // 新文件名
        File file = new File(filePath + fileName);
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        try {
            multipartFile.transferTo(file);
        } catch (Exception e) {
            System.out.println(e.toString());
        }
        return ReturnMessageUtils.success(fileName);
    }

    @Override
    public ReturnMessage<Object> addDeploymentByFileNameBPMN(String deploymentFileUUID, String deploymentName) {
        try {
            String filename = "resources/bpmn/" + deploymentFileUUID;
            Deployment deployment = repositoryService.createDeployment()//初始化流程
                    .addClasspathResource(filename)
                    .name(deploymentName)
                    .deploy();
            //System.out.println(deployment.getName());
            return ReturnMessageUtils.success(deployment.getId());
        } catch (Exception e) {
            return ReturnMessageUtils.error(ErrorEnum.E_ACTIVIT_DEFINITION.getErrorCode(),
                    ErrorEnum.E_ACTIVIT_DEFINITION.getErrorMsg(), e.toString());
        }
    }

    @Override
    public ReturnMessage<Object> addDeploymentByString(String stringBPMN, String deploymentName) {
        try {
            Deployment deployment = repositoryService.createDeployment()
                    .addString("CreateWithBPMNJS.bpmn", stringBPMN)
                    .name(deploymentName)
                    .deploy();
            //System.out.println(deployment.getName());
            return ReturnMessageUtils.success(deployment.getId());
        } catch (Exception e) {
            return ReturnMessageUtils.error(ErrorEnum.E_ACTIVIT_DEFINITION.getErrorCode(),
                    ErrorEnum.E_ACTIVIT_DEFINITION.getErrorMsg(),
                    e.toString());
        }
    }

    @Override
    public ReturnMessage<Object> getDefinitions() {
        try {
            List<HashMap<String, Object>> listMap = new ArrayList<HashMap<String, Object>>();
            List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();

            list.sort((y, x) -> x.getVersion() - y.getVersion());

            for (ProcessDefinition pd : list) {
                HashMap<String, Object> hashMap = new HashMap<>();
                //System.out.println("流程定义ID："+pd.getId());
                hashMap.put("processDefinitionID", pd.getId());
                hashMap.put("name", pd.getName());
                hashMap.put("key", pd.getKey());
                hashMap.put("resourceName", pd.getResourceName());
                hashMap.put("deploymentID", pd.getDeploymentId());
                hashMap.put("version", pd.getVersion());
                listMap.add(hashMap);
            }


            return ReturnMessageUtils.success(listMap);
        } catch (Exception e) {
            return ReturnMessageUtils.error(ErrorEnum.E_ACTIVIT_DEFINITION_GET.getErrorCode(),
                    ErrorEnum.E_ACTIVIT_DEFINITION_GET.getErrorMsg(), e.toString());
        }
    }

    @Override
    public void getProcessDefineXML(HttpServletResponse response, String deploymentId, String resourceName) {
        try {
            InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, resourceName);
            int count = inputStream.available();
            byte[] bytes = new byte[count];
            response.setContentType("text/xml");
            OutputStream outputStream = response.getOutputStream();
            while (inputStream.read(bytes) != -1) {
                outputStream.write(bytes);
            }
            inputStream.close();
        } catch (Exception e) {
            e.toString();
        }
    }

    @Override
    public ReturnMessage<Object> getDeployments() {
        try {

            List<HashMap<String, Object>> listMap = new ArrayList<HashMap<String, Object>>();
            List<Deployment> list = repositoryService.createDeploymentQuery().list();
            for (Deployment dep : list) {
                HashMap<String, Object> hashMap = new HashMap<>();
                hashMap.put("id", dep.getId());
                hashMap.put("name", dep.getName());
                hashMap.put("deploymentTime", dep.getDeploymentTime());
                listMap.add(hashMap);
            }


            return ReturnMessageUtils.success(listMap);
        } catch (Exception e) {
            return ReturnMessageUtils.error(ErrorEnum.E_ACTIVIT_DEFINITION_GET.getErrorCode(),
                    ErrorEnum.E_ACTIVIT_DEFINITION_GET.getErrorMsg(), e.toString());
        }
    }

    @Override
    public ReturnMessage<Object> delDefinition(String depID, String pdID) {
        try {
            //删除数据
            int result = activitFormdataRepository.delete(new QueryWrapper<Formdata>()
                    .eq("procDefId", pdID));

            repositoryService.deleteDeployment(depID, true);
            return ReturnMessageUtils.success(result);


        } catch (Exception e) {
            return ReturnMessageUtils.error(ErrorEnum.E_ACTIVIT_DEFINITION_DEL.getErrorCode(),
                    ErrorEnum.E_ACTIVIT_DEFINITION_DEL.getErrorMsg(), e.toString());
        }
    }

    @Override
    public ReturnMessage<Object> delDefinitionWithNotPdId(String depID) {
        try {
            //把对应的流程定义，流程实例数据都删除
            repositoryService.deleteDeployment(depID, true);
            return ReturnMessageUtils.success();


        } catch (Exception e) {
            return ReturnMessageUtils.error(ErrorEnum.E_ACTIVIT_DEFINITION_DEL.getErrorCode(),
                    ErrorEnum.E_ACTIVIT_DEFINITION_DEL.getErrorMsg(), e.toString());
        }
    }


}
